package com.ruoyi.consumer.controller.facilit.fill;

import ch.qos.logback.classic.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ijpay.core.kit.WxPayKit;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.consumer.aop.annotation.RecordOpeate;
import com.ruoyi.consumer.controller.facilit.api.APIService;
import com.ruoyi.consumer.controller.wallet.RefundService;
import com.ruoyi.consumer.controller.wallet.WalletService;
import com.ruoyi.consumer.domain.*;
import com.ruoyi.consumer.domain.order.PayOrderDTO;
import com.ruoyi.consumer.service.impl.*;
import com.ruoyi.consumer.utils.JsonUtils;
import com.ruoyi.consumer.utils.fill.JsonParserExample;
import com.ruoyi.consumer.utils.pay.Payment;
import io.jsonwebtoken.lang.Assert;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.ruoyi.consumer.utils.JsonUtils.serialize;


/**
 * @author: lizhouwei
 * @ date : 2023/11/24
 * @description:
 */
@Service
public class FillServiceImpl implements FillService {

    private static final Logger logger = (Logger) LoggerFactory.getLogger(JsonUtils.class);

    @Autowired
    private CUserServiceImpl userService;

    @Autowired
    private COrderServiceImpl orderService;

    @Autowired
    private CFillingFacilitServiceImpl cFillingFacilitService;

    @Autowired
    private CRequirementServiceImpl requirementService;

    @Autowired
    private CDeviceOrdersServiceImpl cDeviceOrdersService;

    @Autowired
    private APIService apiService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RefundService refundService;

    @Autowired
    private CWalletPersonServiceImpl cWalletPersonService;

    @Autowired
    private CDealPersonServiceImpl cDealPersonService;

    @Autowired
    private CWalletCompanyServiceImpl cWalletCompanyService;

    @Autowired
    private CDealCompanyServiceImpl cDealCompanyService;

    @Autowired
    private WalletService walletService;


    @Override
    public Double calculateFillVol(Integer orderMoney, Integer orderPrice) {
        Double orderMoneyInYuan = Double.valueOf(orderMoney) / 100;
        Double orderPriceInYuan = Double.valueOf(orderPrice) / 100;
        return orderMoneyInYuan / orderPriceInYuan;
    }

    @Override
    public Double calculateFillMoney(Double orderVol, Double orderPrice) {
        return orderVol * orderPrice;
    }


    @Override
    public AjaxResult payFillNotice(String notifyXml) throws IOException {
        long start = System.currentTimeMillis();
        Map<String, String> stringStringMap = WxPayKit.xmlToMap(notifyXml);
        String out_trade_no = stringStringMap.get("out_trade_no");
        logger.info("订单号：" + out_trade_no);
        //查询微信支付订单
        String s = new Payment().queryOrder(out_trade_no);
        Map<String, String> stringStringMap1 = WxPayKit.xmlToMap(s);
        String attach = stringStringMap1.get("attach");


//      json转为对象
        PayOrderDTO payOrderDTO = JsonUtils.deserialize(attach, PayOrderDTO.class);

        //查询机器信息
        CFillingFacilit cFillingFacilit = cFillingFacilitService.selectCFillingFacilitByFacilitId(Integer.valueOf(payOrderDTO.getSn()));
        Assert.notNull(cFillingFacilit, "设备不存在");

        Boolean waiting = apiService.isWaiting(cFillingFacilit.getFacilitSn(), redisCache.getCacheObject("token:" + "authorizerAccessToken"));
        Assert.isTrue(waiting, "加注机不在待机状态不能下单");

        String openId = stringStringMap.get("openid");
        int total_fee = Integer.parseInt(stringStringMap.get("total_fee"));

        //根据openid查找用户
        CUser user = new CUser();
        user.setOpenid(openId);
        List<CUser> cUsers = userService.selectCUserList(user);
        CUser cUser = new CUser();
        if (!cUsers.isEmpty()) {
            cUser = cUsers.get(0);
        } else {
            return AjaxResult.success("用户不存在");
        }
        //微信扫描
        Object orderId = null;
        if (out_trade_no != null && out_trade_no != "") {
            String[] order = out_trade_no.split("_");
            //添加订单到数据库
            COrder cOrder = new COrder();
            cOrder.setCompanyId(0);
            cOrder.setTargetUserId(cUser.getUserId());
            cOrder.setTargetUserId(cUser.getUserId());
            cOrder.setOrderMoney(total_fee);
            cOrder.setOrderPay(total_fee);
            cOrder.setOrderRefund(0);
            cOrder.setOrderNum(order[0]);
            cOrder.setDealType(2);
            cOrder.setOrderStatus(0);
            int i = orderService.insertCOrder(cOrder);
            Assert.isTrue(i > 0, "添加订单失败");

            //查询单价
            Integer cUnitPrices = cFillingFacilit.getUnitTemporary();

            logger.info("---------------------------------------------");
            logger.info("单价:" + payOrderDTO.getOrderPrice());
            logger.info("微信加注升数:" + payOrderDTO.getOrderVol());
            logger.info("微信加注金额:" + payOrderDTO.getOrderMoney());
            logger.info("---------------------------------------------");

            //构建支付对象
            PayOrderDTO OrderDTO = new PayOrderDTO();
            OrderDTO.setEquipmentName(cFillingFacilit.getFacilitName());
            OrderDTO.setSn(cFillingFacilit.getFacilitSn());
            OrderDTO.setOrderVol(payOrderDTO.getOrderVol());
//            OrderDTO.setOrderVol(50.00);
//            OrderDTO.setOrderPrice(2.00);
            OrderDTO.setOrderPrice(payOrderDTO.getOrderPrice());
            //转换后的金额
            OrderDTO.setOrderMoney(payOrderDTO.getOrderMoney());
//            OrderDTO.setOrderMoney(100.00);
            OrderDTO.setOrderTitle("掌上快运加注");
            OrderDTO.setOrderType(1);
            OrderDTO.setCreateTime(new Date());
            OrderDTO.setSnNumber(payOrderDTO.getSnNumber());
            OrderDTO.setPayType("weixin");
            String s1 = apiService.payOrder(OrderDTO, redisCache.getCacheObject("token:" + "authorizerAccessToken"));

            orderId = null;
            try {
                String jsonString = s1; // 您的 JSON 字符串

                ObjectMapper mapper = new ObjectMapper();

                // 解析 JSON 字符串为 Map
                Map<String, Object> jsonMap = mapper.readValue(jsonString, Map.class);

                System.out.println("jsonMap" + jsonMap);

                // 获取 datas 对象
                Map<String, Object> datas = (Map<String, Object>) jsonMap.get("datas");

                System.out.println("datas" + datas);
                // 获取 manage 对象
                if (datas != null) {
                    orderId = datas.get("id");

                    // 现在 manage 包含您需要的信息
                    System.out.println("orderId" + orderId);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            redisCache.setCacheObject("fillOrderId:" + out_trade_no, orderId);

            //创建实际订单
            CDeviceOrders deviceOrders = new CDeviceOrders();
            deviceOrders.setSn(cFillingFacilit.getFacilitSn());
            deviceOrders.setFillerId(orderId.toString());
            deviceOrders.setOrderFilled(0L);
            deviceOrders.setOrderFilledMoney(0);
            deviceOrders.setOrderMoney(Integer.valueOf(total_fee));
            deviceOrders.setOrderPrice(cUnitPrices);
            deviceOrders.setWeixinOrderId(cOrder.getOrderNum());
            deviceOrders.setOrderType(1);
            deviceOrders.setSnNumber(payOrderDTO.getSnNumber());
            deviceOrders.setStatus(0);

            CRequirement cRequirement = new CRequirement();
            cRequirement.setConsumerId(cUser.getUserId());
            cRequirement.setStatus(1);
            List<CRequirement> requirement = requirementService.selectCRequirementList(cRequirement);
            if (!requirement.isEmpty()) {
                deviceOrders.setRequireId(requirement.get(0).getRequireId());
            }


            int i1 = cDeviceOrdersService.insertCDeviceOrders(deviceOrders);
            Assert.isTrue(i1 > 0, "添加实际订单失败");

            long end = System.currentTimeMillis() - start;
        }
        return AjaxResult.success("支付成功");
    }


    @Override
    @RecordOpeate(desc = "微信小订单")
    public String minOrder(Long orderId, String out_trade_no) throws IOException {

        // 标志来控制任务是否继续执行
        boolean continueTask = false;

        // 标志来控制任务是否继续执行
        boolean continueTaskIsNull = true;

        boolean bigOrderTask = false;

        int count = 0;

        //小订单长度
        int minOrderLength = 0;

        String result = null;
        while (continueTaskIsNull) {
            count++;
            try {
                String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
                result = apiService.findOrderDetailByOrderId(orderId, token);
                if (count > 30) {
                    logger.info("付款未加注,超时自动退款---------数据为" + result);
                    redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                    continueTaskIsNull = false;
                }
                List<DataItem> dataItems = JsonParserExample.parseMinOrder(result);
                if (!dataItems.isEmpty()) {
                    continueTask = true;
                    continueTaskIsNull = false;
                }
                // 等待5秒
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break; // 如果线程被中断，退出循环
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        DataItem data = null;
        while (continueTask) {
            count++;
            try {
                String token = redisCache.getCacheObject("token:" + "authorizerAccessToken");
                result = apiService.findOrderDetailByOrderId(orderId, token);
                List<DataItem> dataItems = JsonParserExample.parseMinOrder(result);

                if (dataItems.isEmpty()) {
                    // 小订单数据从有到无,加注结束
                    logger.info("小订单数据从有到无,加注结束--------数据为" + data);
                    redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                    continueTask = false;

                } else {
                    data = dataItems.get(dataItems.size() - 1);
                    minOrderLength = dataItems.size();
                    logger.info("小订单信息正常,加注中---------最后一条数据为" + data);
                    // 异常情况，突然断电，或者人为停止
                    if (dataItems.size() == minOrderLength) {
                        // 等待10秒
                        logger.info("休眠30秒后再次查询小订单信息------------------");
                        Thread.sleep(30000);
                        result = apiService.findOrderDetailByOrderId(orderId, token);
                        dataItems = JsonParserExample.parseMinOrder(result);
                        if (dataItems.isEmpty()) {
                            // 第二次检查小订单数据为空，视为超时
                            logger.info(" 第二次检查小订单数据为空，加注结束" + data);
                            redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                            continueTask = false;
                        } else {
                            if (dataItems.size() == minOrderLength) {
                                logger.info("第二次检查小订单数据仍然未变化,加注完成---------最后一条数据为" + dataItems.get(dataItems.size() - 1));
                                redisCache.setCacheObject("orderStatus:" + orderId, "加注结束");
                                continueTask = false;
                            } else {
                                // 小订单数据已更新
                                data = dataItems.get(dataItems.size() - 1);
                                minOrderLength = dataItems.size();
                                logger.info("小订单信息正常,加注中---------最后一条数据为" + data);
                            }
                        }
                    }
                }
                // 等待2秒
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break; // 如果线程被中断，退出循环
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        logger.info("查询大订单-----");
        String bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
        BigDataItem bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
        if (apiService.isWorking(bigDataItem)) {
            bigOrderTask = true;
            while (bigOrderTask) {
                try {
                    logger.info("查询大订单-----");
                    bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
                    bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
                    if (!apiService.isWorking(bigDataItem)) {
                        Thread.sleep(5000);
                        bigOrder = apiService.findByOrderId(orderId, redisCache.getCacheObject("token:" + "authorizerAccessToken"));
                        bigDataItem = JsonParserExample.parseBigOrder(bigOrder);
                        bigOrderTask = false;
                    }
                    // 等待10秒
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break; // 如果线程被中断，退出循环
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        System.out.println("大订单信息:" + bigDataItem);

        logger.info("将订单信息存入数据库-----");
        // 将订单信息存入数据库 更新数据库确保数据一致性
        CDeviceOrders cDeviceOrders = new CDeviceOrders();
        cDeviceOrders.setWeixinOrderId(out_trade_no);
        List<CDeviceOrders> realOrders = cDeviceOrdersService.selectCDeviceOrdersList(cDeviceOrders);
        if (realOrders.isEmpty()) {
            Assert.notNull(realOrders, "实际订单不存在");
        }
        CDeviceOrders realOrder = realOrders.get(0);
        realOrder.setOrderFilled(bigDataItem.getOrderVolReal());
        realOrder.setOrderFilledMoney(bigDataItem.getOrderMoneyReal());
        realOrder.setOrderMoney(bigDataItem.getOrderMoney());
        cDeviceOrdersService.updateCDeviceOrders(realOrder);

        logger.info("微信结算找零-----");
        //结算找零
        refundService.processRefund(out_trade_no, bigDataItem.getOrderMoney(), bigDataItem.getOrderMoney() - bigDataItem.getOrderMoneyReal());
        logger.info("更新微信订单-----");
        //更新微信订单
        COrder c_order = new COrder();
        c_order.setOrderNum(out_trade_no);
        List<COrder> cOrders = orderService.selectCOrderList(c_order);
        COrder cOrder = cOrders.get(0);
        cOrder.setOrderAmount(bigDataItem.getOrderVolReal());
        cOrder.setDeviceOrderId(realOrder.getDeviceOrderId());
        cOrder.setOrderPay(bigDataItem.getOrderMoneyReal());
        cOrder.setOrderRefund(bigDataItem.getOrderMoney() - bigDataItem.getOrderMoneyReal());
        orderService.updateCOrder(cOrder);

        logger.info("更新需求订单-----");
        //更新需求订单
        CRequirement cRequirement = requirementService.selectCRequirementByRequireId(realOrder.getRequireId());
        if (cRequirement != null) {
            cRequirement.setStatus(2);
            requirementService.updateCRequirement(cRequirement);
        }


        return null;
    }

    @Override
    public int updateCDealPerson(Integer deviceOrderId, Long amount) {
        //查询交易记录
        CDealPerson cDealPerson = new CDealPerson();
        cDealPerson.setDeviceOrderId(deviceOrderId);
        List<CDealPerson> cDealPeople = cDealPersonService.selectCDealPersonList(cDealPerson);
        Assert.notNull(cDealPeople, "交易记录不存在");
        CDealPerson cDealPerson1 = cDealPeople.get(0);
        cDealPerson1.setDealAmount(amount);
        return cDealPersonService.updateCDealPerson(cDealPerson1);
    }

    @Override
    public int updateCWalletPerson(Integer deviceOrderId, Long amount, Long realAmount) {
        //查询交易记录
        CDealPerson cDealPerson = new CDealPerson();
        cDealPerson.setDeviceOrderId(deviceOrderId);
        List<CDealPerson> cDealPeople = cDealPersonService.selectCDealPersonList(cDealPerson);
        Assert.notNull(cDealPeople, "交易记录不存在");

        //查询用户钱包
        CWalletPerson cWalletPerson = cWalletPersonService.selectCWalletPersonByUserId(cDealPeople.get(0).getUserId());
        Assert.notNull(cWalletPerson, "用户钱包不存在");

        //封装更新前的信息
        Map<String, Object> walletData = walletService.buildWalletInfoMap(cWalletPerson);

        //封装更新后的信息
        cWalletPerson.setWalletFree(cWalletPerson.getWalletFree() + amount - realAmount);
        cWalletPerson.setWalletIncome(cWalletPerson.getWalletOutcome() + realAmount);

        walletService.updateFillPersonWallet(cDealPeople.get(0).getUserId(), -(amount - realAmount));
        CWalletPerson walletPersonLater = cWalletPersonService.selectCWalletPersonByUserId(cDealPeople.get(0).getUserId());
        Map<String, Object> walletData1 = walletService.buildWalletInfoMap(walletPersonLater);

        if (!walletService.walletSignCheck(walletData)) {
            logger.debug("=============sign异常=============");
            //存入异常表
            walletService.saveError(walletData, cWalletPerson, walletPersonLater);
        }


        //更新签名
        logger.debug("=============更新签名=============");
        walletService.updateSign(walletData1);
        return 1;
    }


    @Override
    public int updateCDealCompany(Integer deviceOrderId, Long amount) {
        //查询交易记录
        CDealCompany cDealPerson = new CDealCompany();
        cDealPerson.setDeviceOrderId(deviceOrderId);
        List<CDealCompany> cDealPeople = cDealCompanyService.selectCDealCompanyList(cDealPerson);
        Assert.notNull(cDealPeople, "交易记录不存在");
        CDealCompany cDealPerson1 = cDealPeople.get(0);
        cDealPerson1.setDealAmount(amount);
        return cDealCompanyService.updateCDealCompany(cDealPerson1);
    }

    @Override
    public int updateCWalletCompany(Integer deviceOrderId, Long OrderVol, Long OrderVolReal) {
        //查询交易记录
        CDealCompany cDealCompany = new CDealCompany();
        cDealCompany.setDeviceOrderId(deviceOrderId);
        List<CDealCompany> cDealCompanies = cDealCompanyService.selectCDealCompanyList(cDealCompany);
        Assert.notNull(cDealCompanies, "交易记录不存在");

        //查询用户钱包
        CWalletCompany cWalletCompany = cWalletCompanyService.selectCWalletCompanyByWalletPersonId(cDealCompanies.get(0).getCompanyId());
        Assert.notNull(cWalletCompany, "用户钱包不存在");

        //封装更新前的信息
        Map<String, Object> walletData = walletService.buildCompanyWalletInfoMap(cWalletCompany);

        //封装更新后的信息
        cWalletCompany.setWalletFree(cWalletCompany.getWalletFree() + OrderVol - OrderVolReal);
        cWalletCompany.setWalletIncome(cWalletCompany.getWalletOutcome() + OrderVolReal);
        System.out.println("大订单钱包退款金额");
        walletService.updateFillCompanyWallet(cDealCompanies.get(0).getCompanyId(), -(OrderVol - OrderVolReal));
        CWalletCompany walletCompanyLater = cWalletCompanyService.selectCWalletCompanyByWalletPersonId(cDealCompanies.get(0).getCompanyId());
        Map<String, Object> walletData1 = walletService.buildCompanyWalletInfoMap(walletCompanyLater);

        if (!walletService.walletSignCheck(walletData)) {
            logger.debug("=============sign异常=============");
            //存入异常表
            walletService.saveErrorCompany(walletData, cWalletCompany, walletCompanyLater);
        }


        //更新签名
        logger.debug("=============更新签名=============");
        walletService.updateSign(walletData1);


        //添加个人钱包流水记录
        cDealCompany.setDeviceOrderId(deviceOrderId);
        cDealCompany.setDealOriginalJson(serialize(cWalletCompany));
        cDealCompany.setDealDisposeJson(serialize(cWalletCompany));
        cDealCompany.setDealAmount(cWalletCompany.getWalletFree() + OrderVol - OrderVolReal);
        cDealCompanyService.updateCDealCompany(cDealCompany);

/*        cWalletCompany.setWalletFree(cWalletCompany.getWalletFree() + OrderVol - OrderVolReal);
        cWalletCompany.setWalletIncome(cWalletCompany.getWalletIncome() + OrderVolReal);
        cWalletCompanyService.updateCWalletCompany(cWalletCompany);*/
        return 1;


    }


}
